package com.c3w.synchro.security.service;

import com.c3w.synchro.security.bean.User;
import org.apache.log4j.Logger;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.util.Arrays;
import java.util.List;

/**
 * User: P.Lalonde
 * Date: 12-10-02
 */
@Service("userDetailsService")
public class JpaUserDetailsService implements UserDetailsService {
    private static final Logger LOGGER = Logger.getLogger(JpaUserDetailsService.class);

    private EntityManager entityManager;

    @PersistenceContext
    public void setEntityManager(EntityManager newEm) {
        this.entityManager = newEm;
    }

    /**
     * Cherche un usager dans la base de donnée dont le nom d'usager correspond à celui passé en paramètre.
     *
     * @param username Le nom d'usager.
     * @return L'usager correspondant.
     * @throws UsernameNotFoundException Dans le cas où l'usager ne serait pas trouvé.
     */
    @Transactional
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("User lookup by username. [" + username + "]");
        }

        // assuming that you have a User class that implements UserDetails
        TypedQuery<User> userQuery = entityManager.createQuery("from User where username = :username", User.class);
        userQuery.setParameter("username", username);

        User user = null;
        try {
            user = userQuery.getSingleResult();

            if (user == null) {
                throw new UsernameNotFoundException("User was not found using " + username);
            }

        } catch (NoResultException e) {
            // Advenant qu'on cherche à se logguer admin et que l'usager n'existe pas, on le crée.
            if ("admin".compareTo(username) == 0) {
                // Mot de passe encodé en Md5
                List<SimpleGrantedAuthority> roles = Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN"), new SimpleGrantedAuthority("ROLE_USER"));
                user = new User("admin", "21232f297a57a5a743894a0e4a801fc3", roles);
                entityManager.persist(user);
                entityManager.flush();
            } else {
                throw new UsernameNotFoundException("User was not found using " + username, e);
            }
        }

        return user;
    }
}
